<?

    /**
    * Source Browser
    *
    * @description Browse, view, and download source code in a given directory
    * @author Scott Reynen <scott@randomchaos.com>
    * @copyright Copyright &copy; 2002 Scott Reynen
    * @link http://php.makedatamakense.com/source_browser/
    *
    * This program is free software; you can redistribute it and/or modify
    * it under the terms of the GNU General Public License as published by
    * the Free Software Foundation; either version 2 of the License, or
    * (at your option) any later version.
    * 
    * This program is distributed in the hope that it will be useful,
    * but WITHOUT ANY WARRANTY; without even the implied warranty of
    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    * GNU General Public License for more details: 
    *
    * @license http://www.gnu.org/licenses/gpl.txt GNU GPL
    *
    */

    /**
    * Options you probably want to edit
    */
    
    $directory = '';
    $exclude_directories = array( 'template/styleshout/' );

    /**
    * Options you may want to edit, but probably don't need to
    */
    
    $path_to_here = preg_replace( '#index.php$#' , '' , $_SERVER['PHP_SELF'] );
    $show_extensions = array( 'php' , 'html' );
    $path_base = $_SERVER['DOCUMENT_ROOT'] . '/';
    $url_base = ( isset( $_SERVER['HTTPS'] ) ) ? 
        'https' . '://' . $_SERVER['SERVER_NAME'] . '/' : 
        'http' . '://' . $_SERVER['SERVER_NAME'] . '/';

    $php_syntax_highlight_classes = array(
        '#ff8000' => 'comment' ,
        '#dd0000' => 'quote' ,
        '#0000bb' => 'variable' ,
        '#007700' => 'keyword'
    );

    class file_description {

        var $path , $url , $type , $name;

    } // file_description

    function color_to_class( $matches )
    {
    
        global $php_syntax_highlight_classes;
        
        $class = $php_syntax_highlight_classes[ strtolower( $matches[1] ) ];
        return ( $class != '' ) ? 
            'class="' . $class . '"' :
            'style="color: ' . strtolower( $matches[1] ) . '"';

    } // color_to_class
    
    /**
     * The following function adapted from:
     * @link http://us3.php.net/manual/en/function.highlight-string.php#56642
     */
     
    function xhtml_highlight( $xhtml ) 
    {

        $highlight = highlight_string( stripslashes( $xhtml ) , true );
        $spanned = str_replace( 
            array( '<font ' , '</font>' ) , 
            array( '<span ' , '</span>' ) , 
            $highlight
        );
        $classed = preg_replace_callback( 
            '#color="([^"]+)"#' , 'color_to_class' , $spanned 
        );
        $re_classed = preg_replace_callback( 
            '#style="color: ([^"]+)"#' , 'color_to_class' , $spanned 
        );
        
        return $re_classed;

    } // xhtml_highlight

    function files_in_directory( 
        $directory ,
        $url_path ,
        $show_extensions ,
        $exclude_directories
    ) 
    {

        $files = array();    

        if ( 
            ( ! in_array( $directory , $exclude_directories ) ) && 
            ( $handle = opendir( $directory ) ) 
        ) 
        {
                   
            while ( false !== ( $file_name = readdir( $handle ) ) ) 
            {
            
                $extension_regex = '/.(' . implode( '|' , $show_extensions ) . ')$/';

                if ( preg_match( $extension_regex , $file_name , $match ) )
                {
                
                    $file_description = new file_description();
                    $file_description->name = $file_name;
                    $file_description->path = $directory . $file_name;
                    $file_description->url = $url_path . $file_name;
                    $file_description->type = $match[1];

                    $files[] = $file_description;

                } // if
                
                if ( 
                    ( $file_name{0} != '.' ) && 
                    ( is_dir( $directory . $file_name ) ) 
                )
                {
                
                    $subdirectory_files = files_in_directory( 
                        $directory . $file_name . '/' ,
                        $url_path . $file_name . '/' ,
                        $show_extensions , 
                        $exclude_directories
                    );
                    $files = array_merge( $files , $subdirectory_files );
                
                } // if
                        
                        
            } // while

            closedir( $handle );

        } // if

        return $files;
            
    } // files_in_directory

    foreach ( $exclude_directories as $key => $exclude_directory )
        $exclude_directories[ $key ] = $path_base . $exclude_directory;

    $file_source = ( isset( $_GET['file'] ) ) ? 
        $_GET['file'] : $_GET['source'];

    if ( $file_source != '' )
    {

        if ( substr( $file_source , 0 , 4 ) != 'http' )
            die( 'Sorry, that file could not be opened.' );

        $file = str_replace( $url_base , '' , $file_source );
        
        if ( $file == $file_source )
            die( 'Sorry, that file could not be opened.' );
        
        $content = file_get_contents( $path_base . $file );
        
        $file_name_parts = explode( '/' , $file );
        $file_name = $file_name_parts[ count( $file_name_parts ) - 1 ];
    
    } // if

    if ( isset( $_GET['source'] ) )
    {
    
        /**
        * Download selected file
        */
    
        header("Content-type: application/octet-stream");
        header("Content-Disposition: attachment; filename=" . $file_name );
        header("Pragma: no-cache");
        header("Expires: 0");
        echo( $content );
        die();

    } // if
    else
    {

        ?>
        <html>
            <head>
                <title>Source Browser from MakeDataMakeSense.com</title>
                <style type="text/css">
                
                    body {
                        background: #eee;
                        padding: 20px 40px;
                        }
                        
                    a {
                        color: #c00;
                        }
                        
                        a:hover {
                            color: #900;
                            }
                    
                    .source {
                        margin: 20px 0;
                        background: #fff;
                        height: 400px;
                        overflow: auto;
                        }
                
                        .source .comment {
                            color: #ff8000;
                            }
                        
                        .source .quote {
                            color: #dd0000;
                            }
                            
                        .source .variable {
                            color: #0000bb;
                            }
                        
                        .source .keyword {
                            color: #007700;
                            }
                
                </style>
            </head>
            <body>
                <h1><a href="<?= $path_to_here ?>">Source Browser</a> from <a href="http://php.makedatamakesense.com/source_browser/">MakeDataMakeSense.com</a></h1>
            <?
            
                if (
                    ( ! isset( $_GET['file'] ) ) &&
                    ( ! isset( $_GET['source'] ) )
                )
                {
                
                    /**
                    * Display file list
                    */
            
                    $files = files_in_directory( 
                        $path_base . $directory ,
                        $url_base . $directory ,
                        $show_extensions ,
                        $exclude_directories
                    );
                
                    if ( count( $files ) > 0 )
                    {
        
                        ?>
                        <ul>
                        <?
                
                        foreach ( $files as $file )
                        {
                        
                            ?>
                            <li><a href="<?= $path_to_here ?>?file=<?= urlencode( $file->url ) ?>"><?= $file->url ?></a></li>
                            <?
                        
                        } // foreach
                        
                        ?>
                        </ul>
                        <?
        
                    } // if
                
                } // if
                else 
                {
                    
                    /**
                    * Display selected file
                    */
                            
                    $highlighted_source = xhtml_highlight( $content );
                    
                    ?>
                    <ul>
                        <li><a href="<?= $path_to_here ?>?source=<?= urlencode( $_GET['file'] ) ?>">Download &#8220;<?= $file ?>&#8221;</a></li>
                        <li><a href="<?= $_GET['file'] ?>">Open &#8220;<?= $file ?>&#8221;</a></li>
                    </ul>

                    <div class="source">
                    <?= $highlighted_source ?>
                    </div>
                    <?
                    
                } // else
                
            ?>
            </body>
        </html>
        <?
    
    } // else
    
?>
